package dovs.instructions;

/**
 * A condition in a conditional instruction. Represents a comparison of one
 * value to zero, <code>null</code>, or another value.
 */
public enum Condition {
	EQ, NE, LT, LE, GT, GE, AEQ, ANE;

	/**
	 * The condition equivalent to negating the result of this condition.
	 */
	public Condition negate() {
		switch (this) {
		case EQ:
			return NE;
		case NE:
			return EQ;
		case LT:
			return GE;
		case LE:
			return GT;
		case GT:
			return LE;
		case GE:
			return LT;
		case AEQ:
			return ANE;
		case ANE:
			return AEQ;
		default:
			throw new RuntimeException("Unknown condition");
		}
	}

	/**
	 * The condition equivalent to switching the arguments of this condition.
	 */
	public Condition commute() {
		switch (this) {
		case EQ:
			return EQ;
		case NE:
			return NE;
		case LT:
			return GT;
		case LE:
			return GE;
		case GT:
			return LT;
		case GE:
			return LE;
		case AEQ:
			return AEQ;
		case ANE:
			return ANE;
		default:
			throw new RuntimeException("Unknown condition");
		}
	}

	/**
	 * The <code>if<code> instruction
	 *  comparing a value to zero or null using the given condition.
	 */
	public static String ifName(Condition c) {
		switch (c) {
		case EQ:
			return "ifeq";
		case NE:
			return "ifne";
		case LT:
			return "iflt";
		case LE:
			return "ifle";
		case GT:
			return "ifgt";
		case GE:
			return "ifge";
		case AEQ:
			return "ifnull";
		case ANE:
			return "ifnonnull";
		default:
			throw new RuntimeException("Invalid if condition");
		}
	}

	/**
	 * The <code>if<code> instruction
	 *  comparing two values using the given condition.
	 */
	public static String ifcmpName(Condition c) {
		switch (c) {
		case EQ:
			return "if_icmpeq";
		case NE:
			return "if_icmpne";
		case LT:
			return "if_icmplt";
		case LE:
			return "if_icmple";
		case GT:
			return "if_icmpgt";
		case GE:
			return "if_icmpge";
		case AEQ:
			return "if_acmpeq";
		case ANE:
			return "if_acmpne";
		default:
			throw new RuntimeException("Invalid ifcmp condition");
		}
	}

}
